home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
vsoup11.zip
/
socket.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-02
|
7KB
|
319 lines
// $Id: socket.cc 1.13 1996/09/02 13:30:23 hardy Exp $
//
// This progam/module was written by Hardy Griech based on ideas and
// pieces of code from Chin Huang (cthuang@io.org). Bug reports should
// be submitted to rgriech@ibm.net.
//
// This file is part of soup++ for OS/2. Soup++ including this file
// is freeware. There is no warranty of any kind implied. The terms
// of the GNU Gernal Public Licence are valid for this piece of software.
//
// simple socket class
//
// attention:
// ----------
// TSocket::open requires semaphor support for multithreaded environment.
// For OS/2 it's implemented, but not for any other os!
//
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "mts.hh"
#include "socket.hh"
#include "sema.hh"
TSocket::TSocket( void )
{
State = init;
} // TSocket::TSocket
TSocket::~TSocket()
{
if (State == connected)
close();
} // TSocket::~TSocket
void TSocket::close( void )
{
#ifdef TRACE_ALL
printfT( "TSocket::close()\n" );
#endif
while (State == connecting)
_sleep2( 100 );
if (State == connected) {
#ifdef DEBUG_ALL
printfT( "closing %s:%s/%s\n", ipAdr,service,protocol );
#endif
shutdown( sock,2 );
//// delete ipAdr; ipAdr = NULL;
//// delete service; service = NULL;
//// delete protocol; protocol = NULL;
//// delete Buffer; Buffer = NULL;
}
State = closed;
} // TSocket::close
int TSocket::open( const char *ipAdr, const char *service, const char *protocol,
int buffSize )
//
// Socket öffnen: Parameter sind wohl halbwegs klar...
// - Es muß beim Return aufgepaßt werden, daß State != connecting gesetzt wird - sonst
// wartet der close() u.U. endlos...
// - Open() muß im MT-Fall mit Semaphoren abgesichert werden, da diverse Socket-Fkts
// Zeiger auf statische Struct zurückgeben!
// - der einfachheithalber wird im Fehlerfall mit einem GOTO ans Ende gesprungen. Dort
// wird dann u.a. das Semaphor freigegeben
//
// Return: >=0 -> ok
// < 0 -> failed (im Moment keine weiteren Angaben)
//
{
int Result;
int port;
unsigned long inaddr;
struct sockaddr_in ad;
static TSemaphor OpenSema;
#ifdef TRACE_ALL
printfT( "TSocket::open(%s,%s,%s,%d)\n",ipAdr,service,protocol,buffSize );
#endif
if (State != closed && State != init)
close();
State = connecting;
Result = -1;
OpenSema.Request();
#ifdef DEBUG_ALL
printfT( "opening %s:%s/%s\n", ipAdr,service,protocol );
#endif
memset(&ad, 0, sizeof(ad));
//
// Ist die Adresse als 32bit-IP-Adresse oder als Name angegeben ?
//
inaddr = inet_addr(ipAdr);
if (inaddr != INADDR_NONE) {
ad.sin_family = AF_INET;
ad.sin_addr.s_addr = inaddr;
}
else {
struct hostent *host;
#ifdef DEBUG_ALL
printfT( "TSocket::open: before gethostbyname\n" );
#endif
host = gethostbyname( ipAdr );
if (host == NULL)
goto OpenEnd;
ad.sin_family = host->h_addrtype;
memcpy(&ad.sin_addr, host->h_addr, host->h_length);
#ifdef DEBUG_ALL
printfT( "TSocket::open: behind gethostbyname\n" );
#endif
}
//
// Service auseinanderfieseln
//
if (isdigit(service[0]))
port = htons( atoi(service) );
else {
struct servent *serv;
serv = getservbyname (service,protocol);
if (serv == NULL)
goto OpenEnd;
port = serv->s_port;
}
ad.sin_port = port;
//
// Verbindung aufbauen
//
sock = socket( AF_INET, SOCK_STREAM, 0 );
if (sock < 0)
goto OpenEnd;
if (connect(sock,(struct sockaddr *)&ad,sizeof(ad)) < 0)
goto OpenEnd;
Result = sock;
//
// setup buffer
//
Buffer = new unsigned char [buffSize+10]; ////
TSocket::BuffSize = buffSize;
BuffNdx = BuffEnd = 0;
//
// store ip&protocol
//
TSocket::ipAdr = xstrdup(ipAdr);
TSocket::service = xstrdup(service);
TSocket::protocol = xstrdup(protocol);
OpenEnd:
if (Result >= 0) {
#ifdef DEBUG_ALL
printfT( "socket opened successfully %s,%s/%s\n",
TSocket::ipAdr,TSocket::service,TSocket::protocol );
#endif
State = connected;
}
else
State = closed;
OpenSema.Release();
return Result;
} // TSocket::open
int TSocket::send( void *src, int len )
{
int n;
char *buf = (char *)src;
while (len) {
n = ::send( sock, buf, len, 0 );
if (n <= 0)
return -1;
len -= n;
buf += n;
}
return 0;
} // TSocket::send
int TSocket::printf( const char *fmt, ... )
{
va_list ap;
char buf[BUFSIZ];
int res;
res = -1;
if (State == connected) {
va_start( ap, fmt );
vsprintfT( buf, fmt, ap );
va_end( ap );
res = send( buf, strlen(buf) );
}
return res;
} // TSocket::printf
int TSocket::puts( const char *s )
{
return printf( "%s\n",s ) > 0;
} // TSocket::puts
int TSocket::nextchar( void )
{
if (State != connected || BuffEnd < 0)
return -1;
if (BuffNdx >= BuffEnd) {
BuffEnd = recv( sock, Buffer, BuffSize, 0 );
if (BuffEnd <= 0) {
#ifndef NDEBUG
printfT( "TSocket::nextchar() error: %d\n",errno );
#endif
BuffEnd = -1;
return -1;
}
BuffNdx = 0;
}
return Buffer[BuffNdx++];
} // TSocket::nextchar
char *TSocket::gets( char *buff, int bufflen )
//
// gets from socket ('\n' is not contained in return buff)
// on EOF NULL is returned, otherwise buff
//
{
char *p; // Zeiger auf gelesene Zeichen
int n; // Anzahl der gelesenen Zeichen
int c; // gelesenes Zeichen
if (bufflen <= 1) { // buff muß min. 2 Zeichen lang sein!
#ifdef DEBUG
printfT( "TSocket::gets(): ill bufflen %d\n",bufflen );
#endif
return NULL;
}
p = buff;
n = 0;
for (;;) {
if (n >= bufflen-2) { // if Buffer exhausted, read til '\n'
do
c = nextchar();
while (c != '\n' && c != -1);
break;
}
c = nextchar();
if (c == -1) { // EOF!
if (n == 0) {
*p = '\0';
#ifdef DEBUG
strcpy( buff,"!!EOF!!" );
#endif
return( NULL );
}
else
break;
}
else if (c == '\r') // skip '\r'
continue;
#if 0 // RFC977 caught by reality???
else if (c >= 0x80) { // skip chars >= 0x80 (RFC977!)
#ifndef NDEBUG
printfT( "TSocket::gets(): ill char 0x%02x\n", c);
#endif
continue;
}
#endif
else if (c == '\n') // Zeile fertig !
break;
else {
*(p++) = c;
++n;
}
}
*p = '\0';
return buff;
} // TSocket::gets